﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Printing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication4.service
{
    class PrintPreviewClass
    {
        private string[] lines = null;
        private Image image = null;
        private string StreamType = "";
        private Stream StreamToPrint = null;
        private Font mainFont = new Font("宋体", 12);
        private string fileName = "";
        private PrintPreviewDialog printPreviewDialog = new PrintPreviewDialog();
        private PrintDocument pdDocument = new PrintDocument();
        private PrintPreviewControl printPreviewControl1;

        public void PrintPreview(string filepath, string filetype)
        {
            this.fileName = Path.GetFileNameWithoutExtension(filepath);

            //BeginPrint事件
            pdDocument.BeginPrint += new PrintEventHandler(pdDocument_BeginPrint);
            //PrintPage事件
            pdDocument.PrintPage += new PrintPageEventHandler(pdDocument_PrintPage);
            //EndPrint事件
            pdDocument.EndPrint += new PrintEventHandler(pdDocument_EndPrint);

            //StartPrint打印方法
            FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read);
            StartPrint(fs, filetype);
        }

        /// <summary>
        /// StartPrint打印方法
        /// </summary>
        /// <param name="streamToPrint"></param>
        /// <param name="streamType"></param>
        public void StartPrint(Stream streamToPrint, string streamType)
        {
            //声明返回值的PageSettings
            PageSettings ps = new PageSettings();

            //显示设置打印页对话框
            PageSetupDialog Psdl = new PageSetupDialog();

            //打印多页设置
            PrintDialog pt = new PrintDialog();
            pt.AllowCurrentPage = true;
            pt.AllowSomePages = true;
            pt.AllowPrintToFile = true;

            //form中的打印预览
            printPreviewControl1.Document = pdDocument;
            printPreviewControl1.Zoom = 1.0;
            printPreviewControl1.Dock = DockStyle.Fill;
            printPreviewControl1.UseAntiAlias = true;

            this.StreamToPrint = streamToPrint;//打印的字节流
            this.StreamType = streamType; //打印的类型
            pdDocument.DocumentName = this.fileName; //打印的文件名

            Psdl.Document = pdDocument;
            this.printPreviewDialog.Document = pdDocument;
            this.printPreviewDialog.SetDesktopLocation(300, 800);
            Psdl.PageSettings = pdDocument.DefaultPageSettings;
            pt.Document = pdDocument;

            try
            {
                if (Psdl.ShowDialog() == DialogResult.OK)
                {
                    ps = Psdl.PageSettings;
                    pdDocument.DefaultPageSettings = Psdl.PageSettings;
                }
                if (pt.ShowDialog() == DialogResult.OK)
                {
                    pdDocument.PrinterSettings.Copies = pt.PrinterSettings.Copies;
                }
                if (this.printPreviewDialog.ShowDialog() == DialogResult.OK)
                    pdDocument.Print();
            }
            catch (InvalidPrinterException ex)
            {
                MessageBox.Show(ex.Message, "Simple Editor", MessageBoxButtons.OK, MessageBoxIcon.Error);
                throw;
            }
        }

        /// <summary>
        /// BeginPrint事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void pdDocument_BeginPrint(object sender, PrintEventArgs e)
        {
            char[] param = { '\n' };
            char[] trimParam = { '\r' };
            switch (this.StreamType)
            {
                case "txt":
                    StringBuilder text = new StringBuilder();
                    StreamReader streamReader = new StreamReader(this.StreamToPrint, Encoding.Default);
                    while (streamReader.Peek() >= 0)
                    {
                        lines = streamReader.ReadToEnd().Split(param);
                        for (int i = 0; i < lines.Length; i++)
                        {
                            lines[i] = lines[i].TrimEnd(trimParam);
                        }
                    }
                    break;
                case "image":
                    image = System.Drawing.Image.FromStream(this.StreamToPrint);
                    break;
                default:
                    break;
            }
        }
        /// <summary>
        /// PrintPage事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void pdDocument_PrintPage(object sender, PrintPageEventArgs e)
        {
            int linesPrinted = 0;
            int leftMargin = Convert.ToInt32((e.MarginBounds.Left) * 3 / 4);　 //左边距
            int topMargin = Convert.ToInt32(e.MarginBounds.Top * 2 / 3);　　　 //顶边距
            switch (this.StreamType)
            {
                case "txt":
                    while (linesPrinted < lines.Length)
                    {
                        //向画布中填写内容
                        e.Graphics.DrawString(lines[linesPrinted++], new Font("Arial", 10), Brushes.Black, leftMargin, topMargin, new StringFormat());
                        topMargin += 55;//行高为55，可调整
                        //走纸换页
                        if (topMargin >= e.PageBounds.Height - 60)//页面累加的高度大于页面高度。根据自己需要，可以适当调整
                        {
                            e.HasMorePages = true;
                            printPreviewControl1.Rows += 1;//窗体的打印预览窗口页面自动加1
                            /*
                            * PrintPageEventArgs类的HaeMorePages属性为True时，通知控件器，必须再次調用OnPrintPage()方法，打印一个页面。
                            * PrintLoopI()有一个用於每个要打印的页面的序例。如果HasMorePages是False，PrintLoop()就会停止。
                            */
                            return;
                        }
                    }
                    break;
                case "image":
                    //以下涉及剪切图片
                    int width = image.Width;
                    int height = image.Height;
                    if ((width / e.MarginBounds.Width) > (height / e.MarginBounds.Height))
                    {
                        width = e.MarginBounds.Width;
                        height = image.Height * e.MarginBounds.Width / image.Width;
                    }
                    else
                    {
                        height = e.MarginBounds.Height;
                        width = image.Width * e.MarginBounds.Height / image.Height;
                    }
                    System.Drawing.Rectangle destRect = new System.Drawing.Rectangle(topMargin, leftMargin, width, height);
                    //向画布写入图片
                    for (int i = 0; i < Convert.ToInt32(Math.Floor((double)image.Height / 1600)) + 1; i++)
                    {
                        e.Graphics.DrawImage(image, destRect, i * 1600, i * 900, image.Width, image.Height, System.Drawing.GraphicsUnit.Pixel);
                        //走纸换页
                        if (i * 900 >= e.PageBounds.Height - 60)//页面累加的高度大于页面高度。根据自己需要，可以适当调整
                        {
                            e.HasMorePages = true;
                            printPreviewControl1.Rows += 1;//窗体的打印预览窗口页面自动加1
                            /*
                            * PrintPageEventArgs类的HaeMorePages属性为True时，通知控件器，必须再次調用OnPrintPage()方法，打印一个页面。
                            * PrintLoopI()有一个用於每个要打印的页面的序例。如果HasMorePages是False，PrintLoop()就会停止。
                            */
                            return;
                        }
                    }
                    break;
                default:
                    break;
            }

            //打印完毕后，画线条，且注明打印日期
            //e.Graphics.DrawLine(new Pen(Color.Black), leftMargin, topMargin, e.MarginBounds.Right, topMargin);
            //string strdatetime = DateTime.Now.ToLongDateString() + DateTime.Now.ToLongTimeString();
            //e.Graphics.DrawString(string.Format("打印时间：{0}", strdatetime), this.mainFont, Brushes.Black, e.MarginBounds.Right - 240, topMargin + 40, new StringFormat());

            linesPrinted = 0;
            e.HasMorePages = false;
        }
        /// <summary>  
        /// EndPrint事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void pdDocument_EndPrint(object sender, PrintEventArgs e)
        {
            lines = null;
            image = null;
        }
    }
}
